package com.ruiysoft.crm.controller;

import cn.taroco.common.utils.Query;
import cn.taroco.common.vo.UserVO;
import cn.taroco.common.web.Response;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.additional.query.impl.QueryChainWrapper;
import com.google.common.collect.Lists;
import com.ruiysoft.crm.log.InvokeLog;
import com.ruiysoft.crm.model.ApiResponseEx;
import com.ruiysoft.crm.model.dto.AllocationDTO;
import com.ruiysoft.crm.model.dto.BizClientDTO;
import com.ruiysoft.crm.model.dto.MoveDataDTO;
import com.ruiysoft.crm.model.entity.BizBatchClientRecord;
import com.ruiysoft.crm.model.entity.BizClient;
import com.ruiysoft.crm.model.entity.BizSms;
import com.ruiysoft.crm.model.entity.SysUser;
import com.ruiysoft.crm.model.vo.BizClientVo;
import com.ruiysoft.crm.service.*;
import com.ruiysoft.crm.util.ExcelListener;
import com.ruiysoft.crm.util.HttpClient;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author fanyl
 */
@Slf4j
@Api(tags = "客户信息")
@RestController
@RequestMapping("/client")
public class BizClientController {

    private final BizClientService bizClientService;


    private final IBizCallLogService callLogService;

    private final BizSmsService smsService;
    ApiResponseEx apiResponseEx = new ApiResponseEx();


    private final SysUserService sysUserService;

    private final BizBatchClientRecordService bizBatchClientRecordService;

    public BizClientController(BizClientService bizClientService, IBizCallLogService callLogService, BizSmsService smsService, SysUserService sysUserService, BizBatchClientRecordService bizBatchClientRecordService) {
        this.bizClientService = bizClientService;
        this.callLogService = callLogService;
        this.smsService = smsService;
        this.sysUserService = sysUserService;
        this.bizBatchClientRecordService = bizBatchClientRecordService;
    }

    /**
     * 通过ID查询信息
     *
     * @param id ID
     * @return
     */
    @InvokeLog
    @GetMapping("/get/{id}")
    public BizClient get(@PathVariable Integer id) {
        return bizClientService.getClientById(id);
    }

    /**
     * 分页查询
     *
     * @param params 分页对象
     * @return 分页对象
     */
    @InvokeLog
    @ApiOperation(value = "条件查询客户车辆信息", notes = "条件查询客户车辆信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "客户id", dataType = "Integer"),
            @ApiImplicitParam(name = "mobilePhone", value = "联系电话", dataType = "String"),
            @ApiImplicitParam(name = "carNo", value = "车牌号", dataType = "String"),
            @ApiImplicitParam(name = "firstRegistrationDate", value = "初登日期", dataType = "String")
    })
    @GetMapping("/list/page")
    public IPage dictPage(@RequestParam Map<String, Object> params, UserVO userVO) {

        if (userVO == null || "hanl".equals(userVO.getUsername())) {
            userVO = new UserVO();
            userVO.setUsername("hanl");
//            params.put("client.user_id", "'" + sysUserService.getUserIdByUserName(userVO.getUsername()) + "'");
        } else {
//            List<SysUser> users = callLogService.callTimeLog(userVO);
            SysUser sysUser = sysUserService.getOne(new QueryWrapper<SysUser>().lambda().eq(SysUser::getUsername, userVO.getUsername()));
            StringBuilder createIds = new StringBuilder();
           /* for (int i = 0; users != null && i < users.size(); i++) {
                if (i == 0) {
                    createIds.append("'").append(users.get(0).getUserId()).append("'");
                } else {
                    createIds.append(",'").append(users.get(i).getUserId()).append("'");
                }
            }*/

            params.put("client.user_id", sysUser.getUserId());
        }
        Boolean isAsc = Boolean.parseBoolean(params.getOrDefault("isAsc", Boolean.TRUE).toString());
        String orderByField = (String) params.get("orderByField");
        if (orderByField != null) {
            params.put("order", orderByField);
            params.put("desc", isAsc ? "asc" : "desc");
        }
        return bizClientService.queryClientInfo(new Query<>(params), params);
    }

    /**
     * 添加
     *
     * @param bizClient 客户信息
     * @return success、false
     */
    @InvokeLog
    @ApiOperation(value = "插入客户信息", notes = "插入客户信息")
    @PostMapping("/insert")
    public Response add(@RequestBody BizClient bizClient, UserVO userVO) {
        bizClient.setCreateDate(LocalDateTime.now());
        String userName = userVO.getUsername();
        if (StringUtils.hasText(userName)) {
            int userId = sysUserService.getUserIdByUserName(userName);
            bizClient.setUserId(userId);
        }
        if (!ObjectUtils.isEmpty(bizClientService.getOne(new QueryWrapper<BizClient>().eq("car_no", bizClient.getCarNo())))) {
            return Response.failure("此客户已经存在，不能重复添加");
        }
        if (bizClientService.save(bizClient)) {
            return Response.success(bizClient);
        }
        return Response.failure("添加客户失败！");
    }

    /**
     * 删除
     *
     * @param id 客户id
     * @return R
     */
    @InvokeLog
    @DeleteMapping("/delete/{id}")
    public Response delete(@PathVariable Integer id) {
        return Response.success(bizClientService.removeById(id));
    }

    /**
     * 修改
     *
     * @param bizClient 客户信息
     * @return success/false
     */
    @InvokeLog
    @PutMapping("/update")
    public Response editDict(@RequestBody BizClient bizClient) {
        bizClient.setModificationDate(LocalDateTime.now());

        if (bizClient.getMobilePhone() != null && bizClient.getMobilePhone().contains("****")) {
            bizClient.setMobilePhone(null);
        }
        if (bizClient.getStandbyMobile() != null && bizClient.getStandbyMobile().contains("****")) {
            bizClient.setStandbyMobile(null);
        }

        return Response.success(bizClientService.updateById(bizClient));
    }

    /**
     * 根据批次号撤销数据
     *
     * @param id
     * @return
     */
    @InvokeLog
    @PutMapping("/revoke/{id}")
    public Response revoke(@PathVariable Integer id) {
        Assert.notNull(id, "id不能为空");

        BizBatchClientRecord record = bizBatchClientRecordService.getById(id);
        if (ObjectUtils.isEmpty(record)) {
            return Response.failure("批次记录不存在");
        }

       /* int[] ids = Arrays.stream(record.getClientIds().split(",")).mapToInt(Integer::parseInt).toArray();
        String clientIds = org.apache.commons.lang3.StringUtils.join(ids, ",");*/

        if (bizClientService.revokeAllotUser(record)) {
            return Response.success("撤销数据成功");
        }

        return Response.failure("数据批次撤销失败");
    }


    @InvokeLog
    @ApiOperation(value = "分配数据")
    @PostMapping("/allocation")
    public Response allocationToUser(@RequestParam Map<String, Object> params) {
        if (ObjectUtils.isEmpty(params)) {
            return Response.failure("分配数据不能为空！");
        }

        //去除分页参数
        params.remove("page");
        params.remove("limit");

        Integer userId = (Integer) params.get("userId");
        SysUser userVO = sysUserService.getById(userId);
        String userName = userVO.getRealName();
        params.remove("userId");
        IPage<BizClient> bizClientPage = bizClientService.page(new Query<>(params), new QueryWrapper<>());


        List<BizClient> bizClients = bizClientPage.getRecords();
        for (BizClient bizClient : bizClients) {
            bizClient.setModificationDate(LocalDateTime.now());
            bizClient.setUserId(userId);
            bizClient.setAllocationDate(LocalDateTime.now());
            bizClient.setUserName(userName);
        }

        if (bizClientService.updateBatchById(bizClients)) {
            List<Integer> clientIds = bizClients.stream().map(BizClient::getId).collect(Collectors.toList());
            bizBatchClientRecordService.insert(clientIds, userId, "allot", null, userName);
            return Response.success(true);
        }
        return Response.failure("分配数据失败");
    }


    @InvokeLog
    @ApiOperation(value = "移动数据")
    @PutMapping("/moveData")
    public Response moveData(@RequestBody MoveDataDTO moveDataDTO) {
        if (ObjectUtils.isEmpty(moveDataDTO)) {
            return Response.failure("移动数据不能为空！");
        }
        List<BizClient> bizClients = new ArrayList<>();
        moveDataDTO.getIds().forEach(
                clientId -> {
                    BizClient bizClient = new BizClient();
                    bizClient.setModificationDate(LocalDateTime.now());
                    bizClient.setId(clientId);
                    if (StringUtils.hasText(moveDataDTO.getStatus())) {
                        bizClient.setSuccess(moveDataDTO.getStatus());
                    }
                    bizClients.add(bizClient);
                }
        );
        return Response.success(bizClientService.updateBatchById(bizClients));
    }


    /**
     * excel方式导入客户数据
     *
     * @param file       excel文件
     * @param remark     备注
     * @param isValidate 是否严格校验
     * @param userVO     用户实体类
     * @return
     */
    @InvokeLog
    @PostMapping("/excelImport")
    public Response excelImport(@RequestParam("file") MultipartFile file,
                                @RequestParam("remark") String remark,
                                @RequestParam("isValidate") String isValidate,
                                UserVO userVO) {
        Response response = new Response();
        JSONObject jsonObject = new JSONObject();

        //导入数据保存失败列表
        List<String> failList = Lists.newArrayList();
        //导入用户数据集合
        List<BizClientDTO> clientDTOList = Lists.newArrayList();
        //有效用户数据集合
        List<BizClientDTO> clientList = null;
        int totalNum = 0;

        try {
            ExcelListener<BizClientDTO> excelListener = new ExcelListener();
            ExcelReader excelReader = EasyExcel.read(file.getInputStream(), BizClientDTO.class, excelListener).build();
            ReadSheet readSheet = EasyExcel.readSheet(0).build();
            excelReader.read(readSheet);
            excelReader.finish();
            clientDTOList = excelListener.getDataList();
            if (CollectionUtils.isEmpty(clientDTOList)) {
                return Response.failure("导入数据不能为空");
            }
            totalNum = clientDTOList.size();
            //查询库中所有的车牌号
            List<String> carNos = bizClientService.getCarNos();

            //过滤导入数据中的重复数据和数据库中已存在数据（根据车牌号)
            clientList = clientDTOList.stream()
                    .filter(bizClientDTO -> !carNos.contains(bizClientDTO.getCarNo()))
                    .collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(BizClientDTO::getCarNo))), ArrayList::new));

            //车牌重复列表
            clientDTOList.removeAll(clientList);
            List<String> repeatList = clientDTOList.stream().map(BizClientDTO::getCarNo).collect(Collectors.toList());

            if (!CollectionUtils.isEmpty(repeatList)) {
                jsonObject.put("repeat", String.format("重复车牌号:【%s】", org.apache.commons.lang.StringUtils.join(repeatList, ",")));
            }
        } catch (IOException e) {
            log.error("excel文件解析失败：{}", e);
        }
        if (CollectionUtils.isEmpty(clientDTOList)) {
            return Response.failure("导入数据不能为空");
        }

        if (userVO == null) {
            userVO = new UserVO();
            userVO.setUsername("hanl");
        }
        int userId = sysUserService.getUserIdByUserName(userVO.getUsername());

        List<Integer> clientIds = Lists.newArrayList();
        StringBuilder message = new StringBuilder();

        for (int i = 0; i < clientList.size(); i++) {
            BizClientDTO bizClientDTO = clientList.get(i);
            BizClient bizClient = new BizClient();
            BeanUtils.copyProperties(bizClientDTO, bizClient);

            bizClient.setUserId(userId);
            bizClient.setCreateDate(LocalDateTime.now());
            bizClient.setModificationDate(LocalDateTime.now());

            String carNo = bizClient.getCarNo();

            if ("1".equals(isValidate)) {
                String standbyMobile = bizClient.getStandbyMobile();
                String mobilePhone = bizClient.getMobilePhone();
                String idCard = bizClient.getInsuredIdCard();
                String insured = bizClient.getInsured();
                String engineNumber = bizClient.getEngineNumber();
                String vehicleNo = bizClient.getVehicleNo();

                if (StringUtils.hasText(standbyMobile)) {
                    if (!phoneNumber(standbyMobile)) {
                        message.append("  客户电话2格式错误 \n");
                    }
                }

                if (StringUtils.hasText(mobilePhone)) {
                    if (!phoneNumber(mobilePhone)) {
                        message.append("  客户电话1格式错误 \n");
                    }
                } else {
                    message.append("  客户电话1不能为空 \n");
                }

                if (StringUtils.hasText(idCard)) {
                    if (!idCardNumber(idCard)) {
                        message.append("  被保险人证件号错误 \n");
                    }
                } else {
                    message.append("  被保险人证件号不能为空\n");
                }
                if (StringUtils.isEmpty(insured)) {
                    message.append("  被保险人姓名不能为空\n");
                }
                if (StringUtils.isEmpty(carNo)) {
                    message.append("  车牌号不能为空\n");
                }
                if (StringUtils.isEmpty(engineNumber)) {
                    message.append("  发动机号不能为空\n");
                }
                if (StringUtils.isEmpty(vehicleNo)) {
                    message.append("  车架号不能为空\n");
                }
                if (message.length() > 0) {
                    message.insert(0, "第" + (i + 1) + "条数据存在问题，不允许导入，原因：\n");
                    continue;
                }
            }

            String firstRegistrationDate = bizClientDTO.getFirstRegistrationDate();
            String clivtaEndDate = bizClientDTO.getClivtaEndDate();
            String viEndDate = bizClientDTO.getViEndDate();

            if (!ObjectUtils.isEmpty(firstRegistrationDate)) {
                bizClient.setFirstRegistrationDate(formatDate(firstRegistrationDate));
            }
            if (!ObjectUtils.isEmpty(clivtaEndDate)) {
                bizClient.setClivtaEndDate(formatDate(clivtaEndDate));
            }
            if (!ObjectUtils.isEmpty(viEndDate)) {
                bizClient.setViEndDate(formatDate(viEndDate));
            }

            try {
                if (bizClientService.save(bizClient)) {
                    clientIds.add(bizClient.getId());
                }
            } catch (Exception e) {
                failList.add(bizClient.getCarNo());
                log.error("插入失败{}", e);
            }
        }

        if (message.length() > 0) {
            return Response.failure(message.toString());
        }
        if (!CollectionUtils.isEmpty(clientIds)) {
            //批次号对应数据记录，可根据批次号删除数据
            bizBatchClientRecordService.insert(clientIds, userId, "import", remark, null);
        }

        if (!CollectionUtils.isEmpty(failList)) {
            jsonObject.put("fail", String.format("新增失败车牌号:【%s】", org.apache.commons.lang.StringUtils.join(failList, ",")));
        }
        response.setResult(jsonObject);
        response.setExtMessage("导入数据总数：" + totalNum + ";实际导入：" + clientIds.size() + ";失败：" + (totalNum - clientIds.size()));
        return response;
    }

    /**
     * 批量删除销售数据
     *
     * @param ids 需要删除的数据id集合
     * @return Response 删除结果
     */
    @InvokeLog
    @ApiOperation(value = "批量删除销售数据")
    @Transactional(rollbackFor = Exception.class)
    @DeleteMapping("/delete/batch")
    public Response deleteBatch(@RequestBody List<Integer> ids) {
        if (ObjectUtils.isEmpty(ids)) {
            return Response.failure("参数不能为空");
        }
        return Response.success(bizClientService.removeByIds(ids));
    }


    /**
     * 验证手机号
     *
     * @param number 手机号
     * @return boolean
     */

    private boolean phoneNumber(String number) {
        String rgx = "^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(166)|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9]))\\d{8}$";
        return isCorrect(rgx, number);
    }

    /**
     * 验证身份证号
     *
     * @param number 身份证号
     * @return boolean
     */
    private boolean idCardNumber(String number) {
        String rgx = "^\\d{15}|^\\d{17}([0-9]|X|x)$";
        return isCorrect(rgx, number);
    }

    /**
     * 正则验证
     *
     * @param rgx 正则表达式
     * @param res 验证字符串
     * @return boolean
     */
    private static boolean isCorrect(String rgx, String res) {
        Pattern p = Pattern.compile(rgx);
        if (res == null) {
            return true;
        }
        Matcher m = p.matcher(res);
        return m.matches();
    }


    private LocalDate formatDate(String date) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        return LocalDate.parse(date, formatter);
    }


    @InvokeLog
    @PostMapping("/recv_center")
    public Response recv_center(@RequestBody BizSms bizSms, UserVO userVO) {
        String str = "";
        try {
            int userId = sysUserService.getUserIdByUserName(userVO.getUsername());
            BizClient client = bizClientService.getClientById(Integer.parseInt(bizSms.getClientid()));
            String mobileNo = "";
            if ("1".equals(bizSms.getTag())) {
                mobileNo = client.getMobilePhone();
            } else {
                mobileNo = client.getStandbyMobile();
            }
            String url = "http://qxt.fungo.cn/Recv_center?CpName=hwxy&CpPassword=190722&DesMobile=" + mobileNo + "&Content=" + bizSms.getContent() + "&ExtCode=12";
            str = HttpClient.sendPostRequest(url, null);
            JSONObject objecj = JSONObject.parseObject(str);
            BizSms sms = new BizSms();
            sms.setClientid(bizSms.getClientid());
            sms.setClientname(client.getCarOwner());
            sms.setContent(bizSms.getContent());
            sms.setCreateTime(new Date());
            sms.setMobileno(mobileNo);
            sms.setSmstype("sms");
            sms.setUpdateTime(new Date());
            sms.setUserid(userId + "");
            sms.setUsername(userVO.getUsername());
            if ("0".equals(objecj.get("code"))) {
                sms.setValidflag("1");
            } else {
                sms.setValidflag("0");
            }
            sms.setNote(str);
            smsService.save(sms);
        } catch (Exception e) {
            BizSms sms = new BizSms();
            str = e.toString();
            sms.setNote(str);
            sms.setClientid(bizSms.getClientid());
            sms.setClientname("");
            sms.setContent(bizSms.getContent());
            sms.setCreateTime(new Date());
            sms.setMobileno("");
            sms.setSmstype("sms");
            sms.setUpdateTime(new Date());
            sms.setUserid("");
            sms.setUsername(userVO.getUsername());
            smsService.save(sms);
        }
        return Response.success(str);
    }

    @PostMapping("/recv_center_return")
    public void recv_center_return(String args) {
        String[] arg = args.split(",");
        System.out.println(arg.toString());
        QueryChainWrapper<BizSms> sms = smsService.query().like("note", arg[0]);
        List<BizSms> sms1 = sms.list();
        if (sms1 != null && sms1.size() > 0) {
            BizSms s = sms1.get(0);
            s.setValidflag("0".equalsIgnoreCase(arg[2]) ? "2" : arg[2]);
            smsService.save(s);
        }

    }


    @ApiOperation(value = "根据客户ID查询短信列表", notes = "根据客户ID查询短信列表")
    @GetMapping("/getSms")
    public ApiResponseEx getSMS(@RequestParam Map<String, Object> params, UserVO userVO) throws Exception {
        int userId = sysUserService.getUserIdByUserName(userVO.getUsername());
        apiResponseEx.setData(smsService.getSMS(params, userId));
        return apiResponseEx;
    }

    /**
     * 分页查询
     *
     * @param params 分页对象
     * @return 分页对象
     */
    @ApiOperation(value = "条件查询客户车辆信息", notes = "条件查询客户车辆信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "客户id", dataType = "Integer"),
            @ApiImplicitParam(name = "mobilePhone", value = "联系电话", dataType = "String"),
            @ApiImplicitParam(name = "carNo", value = "车牌号", dataType = "String"),
            @ApiImplicitParam(name = "firstRegistrationDate", value = "初登日期", dataType = "String")
    })
    @InvokeLog
    @GetMapping("/list/batch")
    public IPage batchPage(@RequestParam Map<String, Object> params) {
        StringBuilder createIds = new StringBuilder();
//            IPage<BizBatchClientRecord> page=new I
        //  bizBatchClientRecordService.page(new Query<>(params));
        Wrapper<BizBatchClientRecord> batch = new QueryWrapper<>();
        ((QueryWrapper<BizBatchClientRecord>) batch).orderByDesc("create_date");
        return bizBatchClientRecordService.page(new Query<>(params), batch);
    }


    @InvokeLog
    @ApiOperation(value = "按照批次ID分配数据")
    @PutMapping("/allocationByBatchid")
    public Response allocationByBatchid(String batchid, String userId) {
        SysUser userVO = sysUserService.getById(userId);
        //String userName = userVO.getRealName();
        return Response.success(bizClientService.allocationByBatchid(batchid, userVO));
    }


    @GetMapping("/export")
    public void exportData(@RequestParam Map<String, Object> params, HttpServletResponse response) {

        List<BizClientVo> bizClients = bizClientService.queryClients(params);

        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        try {
            String fileName = URLEncoder.encode("客户数据", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            EasyExcel.write(response.getOutputStream(), BizClientVo.class).sheet("客户数据").doWrite(bizClients);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
